/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package clks.shattered;

import java.awt.FlowLayout;
import java.awt.MouseInfo;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;

/**
 *
 * @author 10135228
 */
public class puzzleBasket implements ActionListener {

    BufferedImage bestFitImage = null;
    BufferedImage[] allImages = null;
    HashMap<String,ArrayList<BufferedImage>> allPieces = new HashMap<>();
    //HashMap<String,ArrayList<BufferedImage>> leftPieces = new HashMap<>();
    //HashMap<String,ArrayList<BufferedImage>> topPieces = new HashMap<>();
    //public static final int TOP = 0, LEFT = 1, INNER = 2;
    
            
    
    
    puzzleBasket(BufferedImage[] images) {
        fill(images);
//              
    }
    
    public BufferedImage getSuitableImage(String Code, Integer[] leftColors, Integer[] topColors){

        final ArrayList<BufferedImage> tmpArray = allPieces.get(Code);
        
        if(tmpArray == null || tmpArray.size()<1){
            System.err.println("no image found ("+Code+")");
            return null;
        }
        if(tmpArray.size()==1) return tmpArray.get(0);
        System.out.println("more than 1 image ("+Code+")("+tmpArray.size()+")");
        Iterator<BufferedImage> it = tmpArray.iterator();
        int mincount = Integer.MAX_VALUE;
        int min2count = Integer.MAX_VALUE;
        bestFitImage = null;
        
        while(it.hasNext()){
            BufferedImage tmpImage = it.next();        
            //new drawPanel(tmpImage);
            Integer[] internLeftColors = getLeftColorArray(tmpImage);
            Integer[] currentPixels;
            int count = 0;
            for (int i = 0; i < internLeftColors.length && leftColors != null; i++) {
                count+=Math.abs((leftColors[i]&0xFF)-(internLeftColors[i])&0xFF);
                //System.out.println("B: "+(leftColors[i]&0xFF)+" - "+(internLeftColors[i]&0xFF)+" = "+Math.abs((leftColors[i]&0xFF)-(internLeftColors[i]&0xFF)));
                count+=Math.abs(((leftColors[i]>>8)&0xFF)-((internLeftColors[i]>>8)&0xFF)); 
                //System.out.println("G: "+((leftColors[i]>>8)&0xFF)+" - "+((internLeftColors[i]>>8)&0xFF)+" = "+(((leftColors[i]>>8)&0xFF)-((internLeftColors[i]>>8)&0xFF)));
                count+=Math.abs(((leftColors[i]>>16)&0xFF)-((internLeftColors[i>>16])&0xFF));
                //System.out.println("R: "+((leftColors[i]>>16)&0xFF)+" - "+((internLeftColors[i>>16])&0xFF)+" = "+(((leftColors[i]>>16)&0xFF)-((internLeftColors[i>>16])&0xFF)));

            }
            Integer[] internTopColors = getTopColorArray(tmpImage, 4);
            for (int i = 0; i < internLeftColors.length && topColors != null; i++) {
                count+=Math.abs((topColors[i]&0xFF)-(internTopColors[i]&0xFF));
                count+=Math.abs(((topColors[i]>>8)&0xFF)-((internTopColors[i]>>8)&0xFF)); 
                count+=Math.abs(((topColors[i]>>16)&0xFF-(internTopColors[i>>16])&0xFF)); 
            }
            System.out.println("End value: "+count);
            if(count < mincount){
                min2count = mincount;
                mincount = count;
                bestFitImage = tmpImage;
            }else if(count<min2count){
                min2count = count;
            }            
        }
        System.out.println("Diff: "+(min2count-mincount));
        if(min2count-mincount<shattered.threshold){
            bestFitImage = null;
            allImages = tmpArray.toArray(new BufferedImage[0]);
            int choice = shattered.getNextChoice();
            System.out.println(choice);
            if(choice ==-1){
                JFrame testframe = new JFrame("?");
                testframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                testframe.setLayout(new FlowLayout());
                for (int i = 0; i <allImages.length; i++) {
                    JButton myButton = new JButton(new ImageIcon(allImages[i]));
                    myButton.setActionCommand(Integer.toString(i));
                    testframe.getContentPane().add(myButton);
                    myButton.addActionListener(this);
                }

                testframe.pack();
                testframe.setLocation(MouseInfo.getPointerInfo().getLocation().x-(testframe.getSize().width/2),MouseInfo.getPointerInfo().getLocation().y-(testframe.getSize().height/2));
                testframe.setVisible(true);
                while(bestFitImage==null){
                    try {
                        //System.out.println("waiting");
                        Thread.sleep(100);
                    } catch (InterruptedException ex) {
                        Logger.getLogger(puzzleBasket.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }else{
                bestFitImage = allImages[choice];
            }
        }
        tmpArray.remove(bestFitImage);
        return bestFitImage;
        
    }   

    
    public Integer[] getLeftColorArray(BufferedImage image) {
        Integer[] tmpArray = new Integer[10];
        Integer[] positionsToGet = new Integer[]{4,5,6,9,12,15,18,21,22,23};
        for (int i = 0; i < positionsToGet.length; i++) {
            tmpArray[i] = image.getRGB(4,positionsToGet[i]);
            tmpArray[i] = image.getRGB(5,positionsToGet[i]);
            //System.out.println(Integer.toHexString(tmpArray[i]));
        }            

        
        return tmpArray;
    }
    
    public Integer[] getTopColorArray(BufferedImage image,int col) {
        Integer[] tmpArray = new Integer[10];
        Integer[] positionsToGet = new Integer[]{4,5,6,9,12,15,18,21,22,23};
        for (int i = 0; i < positionsToGet.length; i++) {
            tmpArray[i] = image.getRGB(positionsToGet[i],col);  
            //System.out.println(Integer.toHexString(tmpArray[i]));
        }        
        return tmpArray;
    }
    
    private void fill(BufferedImage[] images) {
        long timeStart = System.currentTimeMillis();
        String leftCode, topCode;
        for (int i = 0; i < images.length; i++) {
            //System.out.println(i);
            BufferedImage currentPic = images[i];
            leftCode = createLeftCode(currentPic);
            topCode = createTopCode(currentPic);   
            String Code = leftCode + topCode;

            //System.out.println("TopCode = "+topCode);
            //System.out.println("LeftCode = "+leftCode);
            if(allPieces.get(Code)==null){
                ArrayList<BufferedImage> tmpArray = new ArrayList<>();
                tmpArray.add(currentPic);
                allPieces.put(Code,tmpArray);
            }else{
                allPieces.get(Code).add(currentPic);
            }              
            
        }
        long timeEnd = System.currentTimeMillis();
        String format = String.format("%%0%dd", 2);  
        long elapsedTime = (timeEnd-timeStart) / 1000;  
        String seconds = String.format(format, elapsedTime % 60);  
        String minutes = String.format(format, (elapsedTime % 3600) / 60);  
        String hours = String.format(format, elapsedTime / 3600);  
        String time =  hours + ":" + minutes + ":" + seconds; 
        System.out.println("Done building image tree in "+time); 
        //new drawPanel(allPieces.get("").toArray(new BufferedImage[0]));
    }

    private String createLeftCode(BufferedImage currentPic) {
        StringBuilder myBuffer = new StringBuilder("");
        for (int i = 7; i < 21; i+=3) {
            if(currentPic.getRGB(3, i)!=-1 && currentPic.getRGB(4, i)!=-1 && currentPic.getRGB(3, i+1)!=-1 && currentPic.getRGB(4, i+1)!=-1){
                myBuffer.append("1");
            }                
            else if(currentPic.getRGB(5, i)!=-1 && currentPic.getRGB(6, i)!=-1 && currentPic.getRGB(5, i+1)!=-1 && currentPic.getRGB(6, i+1)!=-1){
                myBuffer.append("2");
            }
            else{
                myBuffer.append("3");
            }
        }       
        return myBuffer.toString();
    }

    private String createTopCode(BufferedImage currentPic) {
        StringBuilder myBuffer = new StringBuilder("");
        for (int i = 7; i < 21; i+=3) {
            if(currentPic.getRGB(i, 3)!=-1 && currentPic.getRGB(i, 4)!=-1 && currentPic.getRGB(i+1, 3)!=-1 && currentPic.getRGB(i+1, 4)!=-1){
                myBuffer.append("1");
            }                
            else if(currentPic.getRGB(i, 5)!=-1 && currentPic.getRGB(i, 6)!=-1 && currentPic.getRGB(i+1, 5)!=-1 && currentPic.getRGB(i+1, 6)!=-1){
                myBuffer.append("2");
            }
            else{
                myBuffer.append("3");
            }            
        }          
        return myBuffer.toString();
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        //System.out.println(Integer.decode(((JButton)e.getSource()).getActionCommand()));
        shattered.saveArray.add(Integer.decode(((JButton)e.getSource()).getActionCommand()));
        BufferedImage tmp = allImages[Integer.decode(((JButton)e.getSource()).getActionCommand())];
        ((JFrame)((JButton)e.getSource()).getParent().getParent().getParent().getParent()).dispose();
        bestFitImage = tmp;
        //new drawPanel(bestFitImage);                        
    }
    
}
